import math
import numpy as np
code_k=[]
arr=input('请键入您的信源概率:').split(',')
an = np.array(arr)
num = an.astype(np.float64)#将字符型数组转化为浮点型数组
code =[]
code_dict = {}#编码集

def sort():#将数组从大到小排序
    n=len(num)
    for i in range(n):
        for j in range(1, n-i):
            if  num[j-1] <=num[j] :
                num[j-1],num[j] =num[j], num[j-1]
    return num

def code_length():#求码长
    for p in list_code:
        code_k.append(len(code[p]))
    return code_k

def ave_code():#平均码长
    length_k=0
    for p in list_code:
        length_k +=len(code[p])*p
    return length_k

def u_code(x, code_dict):
    if len(x) == 1:#若数组长度为1
        return 1
    # 判定分组位置
    pos=1#从abs为1开始循环判定
    fpos = 1

    for i in range(len(x)):
        s1 = 0
        s2 = 0
        for i in range(i+1):
            s1 += x[i]
        for j in range(i+1,len(x)):
            s2 += x[j]
        diff = abs(s1 - s2)
        if diff < pos:
            pos = diff
            fpos = i+1
    # 编码
    for i in range(len(x)):
        if i < fpos:
            element = {x[i] : code_dict[x[i]] + '0'}
            code_dict.update(element)
        else:
            element = {x[i] : code_dict[x[i]] + '1'}
            code_dict.update(element)

    # 分组
    leftgroup = []
    rightgroup = []
    for i in range(fpos):
        leftgroup.append(x[i])
    for i in range(fpos, len(x)):
        rightgroup.append((x[i]))
    u_code(leftgroup, code_dict)
    u_code(rightgroup, code_dict)
    return code_dict

def H():#信源熵
    Hx=0
    for i in range(len(num)):
        Hx += num[i] * math.log(num[i], 2) * (-1)
    return Hx

def eff():#编码效率
    e = H()/ave_code()
    return e

def PrintArr():#打印各类数组结果
    print('排序后的信源概率为：{}'.format(num))
    print('各符号码字长度为：{}'.format(code_k))
    print('对应码字：{}'.format(list(code_dict.values())))
    print("平均码长为：{:.3}(bit/symbol)".format(ave_code()))
    print("信源熵为：{:.3}(bit/symbol)".format(H()))
    print('编码效率为：{:.3}%'.format(eff()*100))

#调用函数开始执行
sort()
for i in range(len(num)):# 初始化编码集
    element = {num[i]: ""}
    code_dict.update(element)#update方法更新字典
code = u_code(num, code_dict)
list_code = list(code)
code_length()
ave_code()
H()
eff()
PrintArr()